import base64
import json
import os
import sys
import time
import urllib.parse

import cv2
import numpy as np
import pandas as pd
from paddleocr import PaddleOCR

# 初始化OCR
run_path = os.path.abspath(".")
ocr = PaddleOCR(
    det_model_dir=run_path + "/det/",  # 检测模型目录
    det_max_side_len=1080,  # 图片长边的最大尺寸,超出缩放,正常游戏截图都比较小使用默认基本都可以
    det_db_thresh=0.3,  # 检测模型输出预测图的二值化阈值,影响识别关键0.1-1之间自己调整
    det_db_box_thresh=0.5,  # 检测模型输出框的阈值,低于此值的预测框会被丢弃,影响识别关键0.1-1之间自己调整
    det_db_unclip_ratio=1.1,  # 检测模型输出框扩大的比例,影响识别关键0.1-10之间自己调整正常在0.3-2之间
    rec_model_dir=run_path + '/rec/',  # 识别模型目录
    rec_char_dict_path=run_path + '/rec/dict.txt',  # 识别字典文件
    use_space_char=True,  # 是否识别空格
    max_text_length=100,  # 识别的最大文字长度
    cls_model_dir=run_path + '/cls/',  # 分类模型目录
    use_gpu=False,  # 使用GPU
    lang="ch",  # 模型语言类型,目前支持 中文(ch)、英文(en)及数字  ch=中文+数字+英文
    det=True,  # 使用启动检测
    rec=True,  # 是否启动识别
    cls=False,  # 是否启动分类
)


def my_ocr(img):
    """
    对识别结过进行处理，得到其json格式文件
    :param img:以特定的格式处理完成的需要识别的图像信息
    :return: text_rec:识别出来的文字信息
    """
    try:
        result = ocr.ocr(img, det=True, cls=False)
        ret_rec = {}
        index = 1
        text_rec = ''
        for k, v in result:
            # text = text + v[0]   # 识别到的文字
            text = v[0]
            text_rec = text_rec + v[0]
            score = '{:.3f}'.format(v[1])  # 识别准确率 保留小数点后三位
            # 记录识别框坐标位置
            top_x = str(k[0][0])
            top_y = str(k[0][1])
            bot_x = str(k[2][0])
            bot_y = str(k[2][1])
            ret_rec[str(index)] = {
                "text": text,
                "score": score,
                "top_x": top_x,
                "top_y": top_y,
                "bot_x": bot_x,
                "bot_y": bot_y
            }
            index += 1
        json.dumps(ret_rec, indent=4, ensure_ascii=False)
        ret_recon = str(ret_rec)
        ret_recon = ret_recon.replace("'", "\"")
        file = open("result.json", "w")  # 写入json文件内容
        file.write(ret_recon)
        file.close()
        return text_rec
    finally:
        pass


def text_ocr(src):
    """
    对上传的图片进行编码解码处理，读取其中的信息，最后识别出文本信息
    :param src: 文件路径
    :return: txt:识别出来的文字信息
    """
    img = open(src, mode="rb")  # 文件读取为二进制格式
    base64_data = base64.b64encode(img.read())  # 文件用base64编码
    s = base64_data.decode()
    img = urllib.parse.unquote(s)  # 转换成为url编码
    date_string = time.strftime(
        "%Y-%m-%d-%H-%M-%S")
    name = date_string + ".jpg"
    file = open(name, "wb")
    img_base64 = base64.b64decode(img)  # base64解码
    file.write(img_base64)
    file.close()
    txt = my_ocr(name)
    os.remove(name)
    text = txt
    # print(txt)
    return txt


def mid_get_info(text):
    return text


def handle(src):
    img = cv2.imread(src)
    img_h = img.shape[0]
    img_w = img.shape[1]
    # print("图片高度:", img_h, "图片宽度:", img_w)
    # img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_R = cv2.split(img)[2]  # opencv中三通道排列顺序为BGR
    ret, img_bin = cv2.threshold(img_R, 168, 255, cv2.THRESH_BINARY_INV)  # 二值化阈值选为150，大于150的置0，小于150的置255
    # 霍夫寻线
    kernel_row = np.ones((1, 25))  # 自定义检测横线的核
    img_open_row = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN, kernel_row)  # 开运算检测横线
    kernel_col = np.ones((25, 1))  # 自定义检测竖线的核
    img_open_col = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN, kernel_col)  # 开运算检测竖线
    lines_col = cv2.HoughLinesP(img_open_col, 1, np.pi / 180, 80, minLineLength=int(0.05 * img_h), maxLineGap=5)
    lines_row = cv2.HoughLinesP(img_open_row, 1, np.pi / 180, 80, minLineLength=int(0.4 * img_w), maxLineGap=20)
    # cv2.imshow("img_open_row", img_open_row)
    # cv2.imshow("img_open_col", img_open_col)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    # 通过寻线确定坐标
    lines_x = np.sort(lines_col[:, :, 0], axis=None)
    lines_y = np.sort(lines_row[:, :, 0], axis=None)
    list_x = list(lines_x)
    list_y = list(lines_y)
    # print(list_x, list_y)
    # 合并距离相近的点
    index = 0
    for i in range(len(list_x) - 1):
        if index == 0:
            if (list_x[i] - list_x[i + 1]) ** 2 <= 30 ** 2:
                for t in range(0, i + 1):  # 去除边框左边无用线
                    list_x[t] = list_x[i + 1]
            else:
                index = 1
        else:
            if (list_x[i] - list_x[i + 1]) ** 2 <= 50 ** 2:
                list_x[i + 1] = list_x[i]
    board = 0
    for i in range(len(list_y) - 1):
        if board == 0:
            if (list_y[i] - list_y[i + 1]) ** 2 <= 30 ** 2:
                for t in range(0, i + 1):  # 去除边框上方无用线
                    list_y[t] = list_y[i + 1]
            else:
                board = 1
        else:
            if (list_y[i] - list_y[i + 1]) ** 2 <= 50 ** 2:
                list_y[i + 1] = list_y[i]

    list_x = list(set(list_x))  # 去重
    list_x.sort()  # 排序
    list_y = list(set(list_y))  # 去重
    list_y.sort()  # 排序
    list_y.append(img_h)
    # print(list_x, list_y)
    return list_x, list_y


def select(path):
    # data_table = [[""] * 7 for i in range(3)]
    # data_table = [[""] * 7 for i in range(3)]
    # num = str(num)
    # path = './image/images_' + num + '.png'
    text = text_ocr(path)
    with open('result.json', 'r') as fp:
        json_data = json.load(fp)  # json_data字典类型
    list_x, list_y = handle(path)
    height = list_y[len(list_y) - 1]
    all_top_y = []
    for data in range(1, len(json_data) + 1):
        all_top_y.append(float(json_data[str(data)]["top_y"]))
    all_top_y.sort()
    return list_x, all_top_y, height, text


def find_row_line(path):
    col, line, height, text = select(path)
    try:
        length = len(line)
        line_set = set()
        for i in range(0, length - 1):
            if abs(line[i] - line[i + 1]) <= 10:
                line[i + 1] = line[i]
        lines_count = [0] * 5000
        for i in range(0, length):
            lines_count[int(line[i])] += 1
        record_lines = lines_count.copy()
        lines_count.sort(reverse=True)
        for data in line:
            line_set.add(data)
        # sorted(list(line_set))
        line_set = list(line_set)
        line_set.sort()
        # print(line_set)
        # line_set 为去重之后的纵坐标，筛选出来处理之前的众数，因此可以直接定下来一条线
        # print(record_lines.index(max(lines_count)))
        third_line = record_lines.index((max(lines_count)))
        # print("第三条线纵坐标:", third_line)
        row_line = line_set.copy()
        for data in line_set:
            if data > third_line:
                row_line.remove(data)
        lines = row_line.copy()
        # print("筛选第三条线之后:", row_line)
        final_row = [lines[len(lines) - 1]]
        for i in range(0, len(row_line) - 1):
            if row_line[i] + 55 > row_line[i + 1]:
                lines.remove(row_line[i + 1])
                break
        for i in range(len(lines) - 1, -1, -1):
            if lines[len(lines) - 1] - lines[i] > 100:
                # print(lines[i])
                final_row.append(lines[i])
                break
        if lines[0] > 200:
            final_row.append(140)
        else:
            final_row.append(lines[0])
        if final_row[1] == final_row[2]:
            t = final_row[1]
            final_row.remove(t)
            final_row.append(final_row[0] - 110)
        final_row.sort()
        final_row.append(height)
        # print("竖线:", col)
        # print("横线:", final_row)
        return col, final_row, text
    except IndexError:
        return [], [], text


def find_table(path):
    table_data = [[""] * 7 for _ in range(3)]
    x, y, text = find_row_line(path)
    if len(x) != 0:
        with open('result.json', 'r') as fp:
            json_data = json.load(fp)
        for data in range(1, len(json_data) + 1):
            for i in range(0, len(x) - 1):
                for j in range(0, len(y) - 1):
                    if ((float(json_data[str(data)]["top_x"]) >= x[i]
                         and float(json_data[str(data)]["bot_x"]) <= x[i + 1]
                         and float(json_data[str(data)]["top_y"]) >= y[j]
                         and float(json_data[str(data)]["bot_y"]) <= y[j + 1])):
                        table_data[j][i] = table_data[j][i] + json_data[str(data)]["text"]
                        # print(json_data[str(data)]["text"])
        # print(table_data)
        df = pd.DataFrame(table_data)
        print(df)
    # df.to_excel('answer.xlsx')
    else:
        print(text)


if __name__ == '__main__':

    find_table(sys.argv[1])
